/**
 * HAMMER or HANGING MAN
 * Reversal Patterns :- a reversal pattern does not mean that prices will 
 * reverse, A reversal indicator implies that the prior trend should end.
 * 
 * NOTES:
 * 
 * 1. The real body is at the upper end of the trading range. 
 *    The color of the real body is not important.
 * 2. A long lower shadow should be twice the height of the real body
 * 3. It should have no, or a very short, upper shadow.
 * 
 * VARIATIONS:
 * Lookout for any of the above rules being satisfied. 
 * Eg. Lower shadow need not be twice as long as the body etc.
 * 
 * The longer the lower shadow, the shorter the upper shadow and the
 * smaller the real body the more meaningful the bullish hammer or 
 * bearish hanging man.
 * 
 * Although the real body of the hammer or hanging man can be white or black, 
 * it is slightly more bullish if the real body of the hammer is white, 
 * and slightly more bearish if the real body of the hanging man is black.
 * 
 * (MORE BULLISH)
 * If a hammer has a white real body it means the market sold off 
 * sharply during the session and then bounced back to close at, or near, 
 * the session's high
 * 
 * (MORE BEARISH)
 * If a hanging man has a black real body, it shows that the close could 
 * not get back to the opening price level.
 * 
 * (VERY IMPORTANT) (CANNOT EMPHASISE MORE) 
 * It is especially important that you wait for bearish confirmation 
 * with the hanging man. 
 * 
 * A hammer is a bottom reversal pattern. 
 * So, if it appears on an uptrend it is meaningless
 * 
 * The general principle for the hanging man; the greater the down gap 
 * between the real body of the hanging-man day and the opening the 
 * next day the more likely the hanging man will be a top.
 * 
 * Another bearish verification could be a black real body session with a 
 * lower close than the hanging-man sessions close.
 * 
 * Another bearish confirmation would be for the next day's open to be 
 * under the hanging man's real body.
 * 
 * (WHEN TO BUY)
 *      Make sure bulls are in charge...
 *           Make sure bulls are in charge...
 *                Make sure bulls are in charge ...
 * 
 * If the next day after Hammer is bullish with the next days close above
 * the hammers close.  
 */

package org.mystock.candlestick.service.pattern;

import org.joda.time.DateTime;
import org.mystock.candlestick.dao.DailyMetricsDao;
import org.mystock.candlestick.dao.EventTypeDao;
import org.mystock.candlestick.model.DailyData;
import org.mystock.candlestick.model.Event;
import org.mystock.candlestick.model.EventType;
import org.mystock.candlestick.model.Ticker;
import org.mystock.candlestick.service.util.CandleUtil;

public class HammerOrHangingMan implements Matcher {

	EventTypeDao eventTypeDao;
	DailyMetricsDao dailyDataDao;

	Ticker ticker;

	public HammerOrHangingMan(Ticker ticker) {
		this.ticker = ticker;
	}

	@Override
	public Event match() {

		DateTime toDate = new DateTime();

		DailyData today = dailyDataDao.getDataByDate(ticker, toDate);

		Event event;
		int DAYS_IN_PAST = 5;

		// RULE 1: A long lower shadow should be twice the height of the real
		// body
		// IMPL: 200% of the body

		// RULE 2: It should have no, or a very short, upper shadow
		// IMLP: allowed variance is 25%

		// RULE 3: The real body is at the upper end of the trading range.
		// IMPL: The above check Upper shadow less than 25% confirms the body is
		// at the upper end of the trading range
		if (CandleUtil.checkShortUpperShadow(today, 25) // RULE 2 & RULE 3
				&& CandleUtil.checkLongLowerShadow(today, 200)) { // RULE 1
			event = new Event();

			// TODO - Not accounted for Variation

			DailyData dataPoint1 = dailyDataDao.getDataByDate(ticker, toDate
					.minusDays(DAYS_IN_PAST));
			DailyData dataPoint2 = dailyDataDao.getDataByDate(ticker, toDate);
			float trend = CandleUtil.getTrend(dataPoint1, dataPoint2);

			if (trend > 0) {
				event.setEventType(eventTypeDao
						.getEventByCode(EventType.HANGING_MAN));
				event.setComment("Hanging Man (Lower shadow is "
						+ today.getLowerShadowPercentWRTBody()
						+ "% the body size, Body Color is "
						+ CandleUtil.getBodyColor(today) + ")");
			} else if (trend < 0) {
				event.setEventType(eventTypeDao
						.getEventByCode(EventType.HAMMER));
				event.setComment("Hammer (Lower shadow is "
						+ today.getLowerShadowPercentWRTBody()
						+ "% the body size, Body Color is "
						+ CandleUtil.getBodyColor(today) + ")");
			}

			return event;
		}
		return null;
	}

}
